package myapps.ttclient.udpreceiver;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;

public class ScreenshotReceiver_WithFeedback extends ScreenshotReceiver {

	private static ScreenshotReceiver_WithFeedback _instance;

	public static ScreenshotReceiver getInstance(Activity slideShowActivity, 
			ImageView imageView) {
		try {
			if(_instance == null) {
				_instance = new ScreenshotReceiver_WithFeedback(slideShowActivity, imageView);
			} else {
				_instance.set(slideShowActivity, imageView);
			}

			return _instance;
		} catch (Exception ex) {
			return null;
		}
	}

	public static ScreenshotReceiver_WithFeedback getInstance() {
		return _instance;
	}

	private final static int HEADER_SIZE = 8;
	private final static int SESSION_START = 128;
	private final static int MAX_DATA_SIZE = 65499;

	private DatagramSocket socket;

	private ScreenshotReceiver_WithFeedback(Activity slideShowActivity, 
			ImageView imageView) throws SocketException	{

		this.slideShowActivity = slideShowActivity;

		this.imageView = imageView;

		int port = 11111;

		this.socket = new DatagramSocket(port);

		this.isPaused = true;

		this.runReceivingThread();
	}

	public void runReceivingThread() {
		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					ReceivePacket();
				} catch (Exception e) {

				}

			}
		});

		thread.start();
	}
	
	public void sendFeedback(InetAddress address) throws IOException
	{
		String messageStr="OK ADMIN";
		int server_port = 12345;
		DatagramSocket s = new DatagramSocket();
		//InetAddress local = InetAddress.getByName("0.0.0.0");
		InetAddress local = address;
		int msg_length=messageStr.length();
		byte[] message = messageStr.getBytes();
		DatagramPacket p = new DatagramPacket(message, msg_length,local,server_port);
		s.send(p);
	}


	public void ReceivePacket() throws IOException {

		int currentSession = -1;
		int slicesStored = -1;
		int [] slicesCol = null;
		byte[] imageData = null;
		byte[] buffer = new byte[HEADER_SIZE + MAX_DATA_SIZE];
		boolean sessionAvailable = true;

		try	{
			while (true) {

				if(getIsPaused() == true) {
					Thread.sleep(2000);
					continue;
				}

				DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
				socket.receive(dp);
				
				InetAddress address = dp.getAddress();
				sendFeedback(address);

				byte[] data = dp.getData();

				short session = (short)(data[1] & 0xff);
				short slices = (short)(data[2] & 0xff);
				int maxPacketSize = ((data[3] & 0xff) << 8 | (data[4] & 0xff)); // mask the sign bit
				short slice = (short)(data[5] & 0xff);
				int size = ((data[6] & 0xff) << 8 | (data[7] & 0xff)); // mask the sign bit

				if((data[0] & SESSION_START) == SESSION_START) {
					if(session != currentSession) {
						currentSession = session;
						slicesStored = 0;
						imageData = new byte[slices * maxPacketSize];
						slicesCol = new int[slices];
						sessionAvailable = true;

						Log.d("UDPReceiverThread.ReceivePackage()", "currentSession = " + session);
						Log.d("UDPReceiverThread.ReceivePackage()", "slices = " + slices);
					}
				} // if((data[0] & SESSION_START) == SESSION_START)

				if(sessionAvailable && session == currentSession){

					if(slicesCol != null && slicesCol[slice] == 0) {

						slicesCol[slice] = 1;

						System.arraycopy(data, HEADER_SIZE, imageData, slice * maxPacketSize, size);

						Log.d("UDPReceiverThread.ReceivePackage()", "CurrentSession = " + currentSession + "; " + "Slice = " + slice + " " + 
								"Size = " + size);

						slicesStored++;

					} // if(slicesCol != null && slicesCol[slice] == 0)

					if(slicesStored == slices) {
						try
						{
							final Bitmap bm = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);

							this.slideShowActivity.runOnUiThread(new Runnable() {

								@Override
								public void run() {
									if(getIsPaused() == false) {
										imageView.setImageBitmap(bm);
									}
								}
							});
							System.out.println("All " + slices + "slices are collected.");

							sessionAvailable = false;

							Thread.sleep(100);
						}catch(Exception ex){
							//throw new Exception("BitmapFactory.decodeByteArray()");
						}

					} // if(slicesStored == slices)
				} // if(sessionAvailable && session == currentSession)
			} // while (true)

		}catch(Exception ex) {
			//Log.d("UDPReceiverThread.ReceivePackage()", ex.getMessage());
		}
	}
}
